/*
 * ========================================================
 * Copyright(c) 2014 杭州偶尔科技-版权所有
 * ========================================================
 * 本软件由杭州偶尔科技所有, 未经书面许可, 任何单位和个人不得以
 * 任何形式复制代码的部分或全部, 并以任何形式传播。
 * 公司网址
 * 
 * 			http://www.kkkd.com/
 * 
 * ========================================================
 */

package com.ouertech.android.agm.lib.base.future.main;

import android.content.Context;

import com.ouertech.android.agm.lib.base.future.core.AgnettyFuture;
import com.ouertech.android.agm.lib.base.future.core.AgnettyFutureListener;
import com.ouertech.android.agm.lib.base.future.core.AgnettyHandler;
import com.ouertech.android.agm.lib.base.future.core.event.ExceptionEvent;
import com.ouertech.android.agm.lib.base.future.core.event.MessageEvent;
import com.ouertech.android.agm.lib.base.future.main.*;
import com.ouertech.android.agm.lib.base.future.main.MainEvent;
import com.ouertech.android.agm.lib.base.future.main.MainHandler;
import com.ouertech.android.agm.lib.base.utils.UtilLog;

import java.lang.reflect.Constructor;

/**
 * @author : Zhenshui.Xia
 * @date   : 2013-9-19
 * @desc   : 
 */
public class MainFuture extends AgnettyFuture {
	private MainHandler mHandler;

	public MainFuture(Context context) {
		super(context);
	}


	/**
	 * 执行任务，返回任务的ID,如果该任务正在运行，则不会重复执行该任务
	 * @return
	 */
	public synchronized String execute(){
		//任务失败假如当前的任务正在被执行
		if(mFutureManager.getFutureByID(mFutureID) != null) {
			UtilLog.e(toString() + "Can't exec future while it's running!");
			return mFutureID;
		}

		mMainThread = Thread.currentThread().getName().equals("main");
		if(!mMainThread) {
			UtilLog.e(toString() + "Can't exec main future in non main thread!");
			return mFutureID;
		}

		mFutureManager.addFuture(this);
		mFutureManager.execMainFuture(this);
		return mFutureID;
	}

	@Override
	public void run() {
		//首次实例化任务处理器
		if(mHandler == null) {
			//没有设置任务处理器,使用默认的本地任务处理器，DefaultLocalHandler
			if(mHandlerCls == null) {
				mHandler = new MainDefaultHandler(mContext);
			} else {
				try {
					Constructor<? extends AgnettyHandler> constructor
													= mHandlerCls.getConstructor(Context.class);
					mHandler = (MainHandler)constructor.newInstance(mContext);
				} catch (Exception ex) {
					throw new RuntimeException(ex);
				} 
			}
		}
		
		if(mListener != null) mListener.setFuture(this);
		
		//执行任务
		try {
			MessageEvent evt = new MainEvent();
			evt.setFuture(this);
			evt.setData(mData);
			mHandler.onExecute(evt);
			if(!mFinished && mAutoCommit) commitComplete(null, false);
		} catch(Exception ex) {
			ExceptionEvent evt = new ExceptionEvent();
			evt.setFuture(this);
			evt.setException(ex);
			mHandler.onException(evt);
			if(!mFinished && mAutoCommit) commitException(null, ex, false);
		} finally {
			mHandler.onDispose();
		}
	}
	

	@Override
	public String getName() {
		String futureName = mHandlerCls==null ? MainDefaultHandler.class.getName() : mHandlerCls.getName();
		return futureName;
	}



	public static class Builder {
		private Context mContext;
		
		private Class<? extends AgnettyHandler> mHandlerCls;
		private Object mData;
		private AgnettyFutureListener mListener;
		private Object mTag;
		private boolean mAutoCommit;
		
		public Builder(Context context) {
			this.mContext = context;
			this.mAutoCommit = true;
		}
		
		/**
		 * 设置任务处理器
		 * @param handler
		 * @return
		 */
		public Builder setHandler(Class<? extends AgnettyHandler> handler) {
			this.mHandlerCls = handler;
			return this;
		}
		
		/**
		 * 设置任务处理器执行数据
		 * @param data
		 * @return
		 */
		public Builder setData(Object data) {
			this.mData = data;
			return this;
		}
		
		/**
		 * 设置任务监听器
		 * @param listener
		 * @return
		 */
		public Builder setListener(AgnettyFutureListener listener) {
			this.mListener = listener;
			return this;
		}
		
		/**
		 * 设置任务标记
		 * @param tag
		 * @return
		 */
		public Builder setTag(Object tag) {
			this.mTag = tag;
			return this;
		}

		/**
		 * 设置任务完成（或异常）后是否自动提交
		 * @param autoCommit
		 * @return
		 */
		public Builder setAutoCommit(boolean autoCommit) {
			mAutoCommit = autoCommit;
			return this;
		}


		/**
		 * 创建一个本地任务
		 * @return
		 */
		public MainFuture create() {
			final MainFuture future = new MainFuture(mContext);
			
			future.mHandlerCls = mHandlerCls;
			future.mData = mData;
			future.mListener = mListener;
			future.mTag = mTag;
			future.mAutoCommit = mAutoCommit;
			return future;
		}
		
		/**
		 * 异步执行任务
		 * @return
		 */
		public MainFuture execute() {
			MainFuture future = create();
			future.execute();
			return future;
		}
	}
}
